﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace TARLib
{
    public class VassoioCollection : IList<Vassoio>
    {
        private List<Vassoio> _InternalList;

        public VassoioCollection()
        {

        }

        public VassoioCollection(int comandaID, int puntoDistribuzioneID, string tavoloAssegnato, string codiceComanda, string note, DateTime dataOra, string autore, ProdottoOrdinatoCollection prodotti)
        {
            // Questo costruttore crea i vassoi!
            _InternalList = new List<Vassoio>();
            int progressivoVassoio = 0;

            List<ProdottoOrdinato> prodottiOrdinati = prodotti.OrderBy(o => o.CodiceProdottoBarcode).ToList();
            Vassoio currentVassoio = null;
            for (int i = 0; i < prodottiOrdinati.Count; i++)
            {
                if (currentVassoio == null)
                {
                    progressivoVassoio = 1;
                    currentVassoio = new Vassoio(null, comandaID, progressivoVassoio, 0, puntoDistribuzioneID, tavoloAssegnato, codiceComanda, note, dataOra, autore, new ProdottoOrdinatoCollection(), false);
                }

                if (currentVassoio.Prodotti.Sum(o => o.PercentualeVassoio) + prodottiOrdinati[i].PercentualeVassoio > 100)
                {
                    // Aggiungi il vassoio alla lista
                    _InternalList.Add(currentVassoio);
                    // Crea nuovo vassoio
                    progressivoVassoio++;
                    currentVassoio = new Vassoio(null, comandaID, progressivoVassoio, 0, puntoDistribuzioneID, tavoloAssegnato, codiceComanda, note, dataOra, autore, new ProdottoOrdinatoCollection(), false);
                    currentVassoio.Prodotti.Add(prodottiOrdinati[i]);
                }
                else
                {
                    // Aggiungi il prodotto al vassoio corrente
                    currentVassoio.Prodotti.Add(prodottiOrdinati[i]);
                }
            }
            // Aggiungi il vassoio in corso
            if (currentVassoio != null)
                _InternalList.Add(currentVassoio);

            // Abbina il NTotaleVassoi
            foreach (Vassoio v in _InternalList)
            {
                v.NTotaleVassoi = _InternalList.Count();
            }

            // Verifica
            if (_InternalList.SelectMany(o => o.Prodotti).Count() != prodotti.Count)
            {
                throw new Exception("Il numero di prodotti non coincide (vassoi e prodotti in ingresso)");
            }
        }

        public VassoioCollection(int comandaID)
        {
            _InternalList = new List<Vassoio>();

            // Carica da Comanda
            SqlConnection conn = new SqlConnection(Database.GetDBConnectionString());
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = "[Cucina].[SP_VassoiByComandaID_CL]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@ComandaID", System.Data.SqlDbType.Int) { Value = comandaID });

            SqlDataReader dr = null;
            try
            {
                conn.Open();
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    _InternalList.Add(new Vassoio(
                        (int)dr["VassoioID"],
                        (int)dr["ComandaID"],
                        (int)dr["Progressivo"],
                        (int)dr["NTotaleVassoi"],
                        (int)dr["PuntoDistribuzioneID"],
                        dr["TavoloAssegnato"] == DBNull.Value ? null : dr["TavoloAssegnato"].ToString(),
                        dr["CodiceComanda"].ToString(),
                        dr["Note"] == DBNull.Value ? null : dr["Note"].ToString(),
                        (DateTime)dr["DataOra"],
                        dr["Autore"].ToString(),
                        new ProdottoOrdinatoCollection(),
                        (bool)dr["IsConsegnato"]));
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (dr != null)
                {
                    dr.Close();
                    dr.Dispose();
                }
                cmd.Dispose();
                conn.Close();
                conn.Dispose();
            }

            // A questo punto carica le collection associate
            foreach (Vassoio v in _InternalList)
            {
                v.Prodotti.CaricaDaVassoioID(v.VassoioID.Value);
            }
        }

        public void Salva(System.Data.SqlClient.SqlTransaction trans)
        {
            // Non è supportata la procedura di update, il salvataggio della collection
            // prevede la cancellazione di tutti gli elementi e il successivo re-inserimento

            int comandaID = -1;
            if (_InternalList.Select(o => o.ComandaID).Distinct().Count() != 1)
            {
                throw new Exception("Impossibile determinare ComandaID univoco per la collection VassoioCollection");
            }
            else
            {
                comandaID = _InternalList.Select(o => o.ComandaID).Distinct().First();
            }

            SqlCommand cmd = new SqlCommand();
            cmd.Transaction = trans;
            cmd.Connection = trans.Connection;
            cmd.CommandText = "[Cucina].[SP_Vassoio_DA]";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@ComandaID", System.Data.SqlDbType.Int) { Value = comandaID });
            try
            {
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }

            foreach (Vassoio v in _InternalList)
            {
                v.Salva(trans);
            }
        }

        #region IList<Vassoio> Members

        public int IndexOf(Vassoio item)
        {
            return _InternalList.IndexOf(item);
        }

        public void Insert(int index, Vassoio item)
        {
            _InternalList.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            _InternalList.RemoveAt(index);
        }

        public Vassoio this[int index]
        {
            get
            {
                return _InternalList[index];
            }
            set
            {
                _InternalList[index] = value;
            }
        }

        #endregion

        #region ICollection<Vassoio> Members

        public void Add(Vassoio item)
        {
            _InternalList.Add(item);
        }

        public void Clear()
        {
            _InternalList.Clear();
        }

        public bool Contains(Vassoio item)
        {
            return _InternalList.Contains(item);
        }

        public void CopyTo(Vassoio[] array, int arrayIndex)
        {
            _InternalList.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return _InternalList.Count; }
        }

        public bool IsReadOnly
        {
            get { return ((IList<Vassoio>)_InternalList).IsReadOnly; }
        }

        public bool Remove(Vassoio item)
        {
            return _InternalList.Remove(item);
        }

        #endregion

        #region IEnumerable<Vassoio> Members

        public IEnumerator<Vassoio> GetEnumerator()
        {
            return _InternalList.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return _InternalList.GetEnumerator();
        }

        #endregion
    }
}
